<template>
  <div class="rev-table relation-table">
    <template v-if="columns?.length > 0">
      <grid-form
        v-if="pageQuery && pageQuery.grid"
        ref="queryMeta"
        v-model="conditions"
        :fields="columns"
        :page="pageQuery"
        module="query"
      >
        <el-button size="default" type="primary" class="ml10" @click="getList()"> 查询 </el-button>
        <el-button size="default" class="ml10" @click="resetQuery()"> 重置 </el-button>
      </grid-form>
    </template>
    <div class="query-tools" v-if="source && operations?.length && !isFormReadOnly">
      <div class="query-left">
        <template v-for="op in operations" :key="op.key">
          <el-upload
            v-if="op.key === 'import'"
            ref="uploadRef"
            class="query-upload"
            action="/api/table/import"
            :auto-upload="true"
            :show-file-list="false"
            :data="{ key: 'import', source }"
            v-auths="getPermissions(op?.permissions)"
            :on-success="onUploadSuccess"
          >
            <template #trigger>
              <el-button class="op-btn" size="default">
                {{ op.name }}
              </el-button>
            </template>
          </el-upload>
          <el-dropdown
            v-else-if="op.type === 'search_export' && hasPermissions(op?.permissions)"
            :disabled="op._loading"
            split-button
            size="default"
            @click="downloadList('page', op)"
            @command="(cmd) => downloadList(cmd, op)"
            style="margin-right: 12px"
          >
            导出
            <template #dropdown>
              <el-dropdown-menu>
                <el-dropdown-item command="page">导出当前页</el-dropdown-item>
                <el-dropdown-item command="select">导出选择数据</el-dropdown-item>
                <el-dropdown-item command="all">导出全部</el-dropdown-item>
              </el-dropdown-menu>
            </template>
          </el-dropdown>
          <template
            v-else-if="op.type === 'editRow' && op.bytable && hasPermissions(op.permissions)"
          >
            <template v-if="form?.id && isActiveStatus(form)">
              <el-button
                size="default"
                class="op-btn"
                type="primary"
                @click.stop="saveEditRow(form, op)"
                :key="op.key + 'editSave'"
              >
                保存
              </el-button>
              <el-button
                size="default"
                class="op-btn"
                type="info"
                @click.stop="cancelEditRow(form)"
                :key="op.key + 'editCancel'"
              >
                取消
              </el-button>
            </template>
            <el-button
              size="default"
              class="op-btn"
              :type="op.genre"
              :title="op.hint"
              @click.stop="doOperation(op)"
              :key="op.key"
              v-else
            >
              {{ op.name }}
            </el-button>
          </template>
          <el-button
            v-else-if="op.bytable"
            :loading="op._loading"
            size="default"
            class="op-btn"
            :type="op.genre"
            :title="op.hint"
            @click="doOperation(op)"
            v-auths="getPermissions(op?.permissions)"
          >
            {{ op.name }}
          </el-button>
        </template>
      </div>
    </div>
    <div class="main-table">
      <meta-table
        v-if="columns.length"
        v-loading="isLoading"
        v-model:selection="multipleSelection"
        ref="mainTableRef"
        :source="source"
        :meta="columns"
        :operations="operations"
        :list="dataList"
        :slotColumns="slotColumns"
        :showSelect="!!(operations && operations.some((o) => o.bytable))"
        :showOperation="showOperation"
        :config="{ ...tableConfig, height: 'unset', 'max-height': 'unset' }"
        :readonly="readonly"
        @delete-row="showDelete"
        @edit-row="showEdit"
        @edit-save="editSave"
        @sort-change="sortChange"
        @current-change="currentChange"
        @cell-operation="onCellOperation"
      >
        <template #operator="scope">
          <template v-for="op in getShowButtons(scope.row)">
            <template v-if="op.type === 'editRow' && op.byitem">
              <template v-if="isActiveStatus(scope.row)">
                <el-button
                  size="small"
                  link
                  type="primary"
                  @click.stop="saveEditRow(scope.row, op)"
                  :key="op.key + 'editSave'"
                >
                  保存
                </el-button>
                <el-button
                  size="small"
                  link
                  type="info"
                  @click.stop="cancelEditRow(scope.row)"
                  :key="op.key + 'editCancel'"
                >
                  取消
                </el-button>
              </template>
              <el-button
                size="small"
                link
                :type="op.genre || 'primary'"
                @click.stop="doOperation(op, scope.row)"
                :key="op.key"
                v-else
              >
                {{ op.name }}
              </el-button>
            </template>
            <el-button
              size="small"
              link
              :type="op.genre || 'primary'"
              @click.stop="doOperation(op, scope.row)"
              v-else-if="op.byitem"
              :key="op.key"
            >
              {{ op.name }}
            </el-button>
          </template>
          <template
            v-if="relation?.selections && hasPermissions(relation?.selections?.permissions)"
          >
            <el-button size="small" link type="primary" @click.stop="doDeleteTableData(scope.row)">
              删除
            </el-button>
          </template>
        </template>
        <template #column="scope" v-if="slotColumns && slotColumns.length > 0">
          <slot name="column" :row="scope.row" :column="scope.column"></slot>
        </template>
      </meta-table>
    </div>
    <div class="table-dashed-add">
      <template v-for="(selections, idx) in relationSelections" :key="idx">
        <el-button
          class="button-dashed-add"
          v-if="selections && !readonly"
          size="default"
          @click="openSelection(selections, idx)"
        >
          + {{ selections.name || '新增' }}
        </el-button>
      </template>
    </div>
    <div class="table-pagination" v-if="source && total > 100">
      <el-pagination
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="query.page"
        :page-sizes="[10, 20, 50, 100]"
        :page-size="query.size"
        layout="total, sizes, prev, pager, next, jumper"
        background
        :total="total"
      />
    </div>

    <!-- <RevRelations
      v-if="currenForm?.id"
      :readonly="true"
      :relations="relations"
      :form="currenForm"
    /> -->

    <el-dialog
      append-to-body
      modal-class="relation-dialog"
      :title="
        isFormReadOnly ? '详情' : refOp ? refOp.name : form?.hasOwnProperty('id') ? '编辑' : '新增'
      "
      :fullscreen="isFullScreen"
      :close-on-press-escape="false"
      :close-on-click-modal="false"
      v-model="dialogVisible"
      width="50%"
      @closed="dialogClose"
    >
      <grid-form
        v-if="pageForm && pageForm.grid"
        ref="form"
        v-model="form"
        :fields="columns"
        :page="pageForm"
        module="form"
        :readonly="isFormReadOnly"
      />
      <meta-form
        v-else-if="dialogVisible"
        ref="form"
        v-model="form"
        :readonly="isFormReadOnly"
        :meta="columns"
      />
      <RevRelations
        ref="relationRef"
        v-if="dialogVisible"
        :relations="relations"
        :page="{ ...mainPage, ...config.page }"
        :readonly="isFormReadOnly"
        :form="form"
      />
      <template #footer>
        <span class="dialog-footer">
          <el-button size="default" @click="dialogVisible = false">取 消</el-button>
          <el-button
            type="primary"
            size="default"
            v-if="!form?.id || (!isFormReadOnly && form?.approvalStatus != 1)"
            :disabled="isLoading || isBasicLoading"
            @click="doSave"
          >
            {{ refOp?.saveButtonName || '保 存' }}
          </el-button>
        </span>
      </template>
    </el-dialog>
    <el-dialog
      append-to-body
      modal-class="relation-dialog"
      :title="formOp ? formOp.name : ''"
      :fullscreen="isFullScreen"
      v-model="formDialogVisible"
      width="50%"
      @closed="formDialogClose"
    >
      <grid-form
        v-if="formPage?.form && formPage?.form?.grid"
        ref="form"
        v-model="form"
        :fields="formFields"
        :page="formPage?.form"
        :readonly="isFormReadOnly"
      />
      <meta-form
        v-else-if="formDialogVisible"
        ref="form"
        v-model="form"
        :readonly="isFormReadOnly"
        :meta="formFields"
      />
      <RevRelations
        ref="relationRef"
        v-if="formDialogVisible && formPage?.relations"
        :relations="formPage?.relations"
        :page="formPage"
        :readonly="isFormReadOnly"
        :form="form"
      />
      <template #footer>
        <span class="MetaDialog-footer">
          <el-button size="default" @click="formDialogVisible = false">取 消</el-button>
          <el-button
            type="primary"
            size="default"
            :disabled="isLoading || isBasicLoading"
            @click="doSave"
            >确 定</el-button
          >
        </span>
      </template>
    </el-dialog>
    <el-dialog
      append-to-body
      modal-class="relation-dialog"
      :title="'选择'"
      v-model="selectionDialogVisible"
      width="50%"
      @closed="dialogClose"
    >
      <div class="layout-full select-dialog">
        <grid-form
          v-if="selectionDialogVisible && selectionQuery && selectionQuery.grid"
          ref="selectionQueryMeta"
          v-model="selectionConditions"
          :fields="selectionFields"
          :page="selectionQuery"
        >
          <el-checkbox v-model="isLike" class="mr10" label="模糊查询" size="default" />
          <el-button size="default" type="primary" @click="getSelectionList()"> 查询</el-button>
          <el-button size="default" @click="resetSelectQuery">重置</el-button>
        </grid-form>
        <meta-query
          v-else-if="selectionDialogVisible"
          ref="selectionQueryMeta"
          v-model="selectionConditions"
          :source="selectionOp?.selection?.source"
          :meta="selectionFields"
        >
          <el-checkbox v-model="isLike" class="mr10" label="模糊查询" size="default" />
          <el-button size="default" type="primary" @click="getSelectionList()"> 查询</el-button>
          <el-button size="default" @click="resetSelectQuery">重置</el-button>
        </meta-query>
        <div class="main-table">
          <meta-table
            v-model:selection="selectionSelected"
            ref="selectionTableRef"
            :source="selectionOp?.selection?.source"
            :meta="selectionFields"
            :list="selectionList"
            :config="{
              ...tableConfig,
              'edit-config': {
                enabled: false
              }
            }"
          />
        </div>
        <div class="table-pagination" v-if="selectionOp?.selection?.source">
          <el-pagination
            @size-change="handleSizeChangeSelection"
            @current-change="handleCurrentChangeSelection"
            :current-page="selectionPagination.page"
            :page-sizes="[10, 20, 50, 100]"
            :page-size="selectionPagination.size"
            layout="total, sizes, prev, pager, next, jumper"
            background
            :total="selectionTotal"
          />
        </div>
      </div>
      <template #footer>
        <span class="dialog-footer">
          <el-button size="default" @click="selectionDialogVisible = false">取 消</el-button>
          <el-button size="default" type="primary" @click="addSelection()">确 定</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script>
import { h, defineAsyncComponent } from 'vue'
import {
  getTableMeta,
  getTableList,
  getTableItem,
  addTableData,
  editTableData,
  auditTableData,
  auditAllTableData,
  deleteTableData,
  exportTableData,
  generalOperation,
  doApi,
  doAjaxDownload
} from '/@/api/basic'
import { MetaForm, MetaTable, MetaQuery } from './meta'
import {
  initForeignValues,
  initSelectValues,
  getGridDefaultValue,
  isUniqueData,
  getPermissions,
  checkVisible,
  checkDisabled,
  hasPermissions,
  doPreview
} from './utils/table'
import { Dialog } from './Dialog'
import { ElMessage, ElMessageBox, ElLoading as Loading } from 'element-plus'
import GridForm from './AutoGrid/index.vue'
import { getTemplateData } from './AutoGrid/tool'
import { intersection, template } from 'lodash-es'
import { downloadLists, getRouteParams } from '/@/modules/utils/table'
import func from '/@/modules/utils/func'
import { isNullOrUnDef } from '/@/utils/is'
// import testData from "./test.json"

const modules = import.meta.glob('../views/**/*.{vue,tsx}')

export default {
  name: 'RevTable',
  components: { MetaTable, MetaForm, MetaQuery, GridForm },
  props: {
    // 关系表配置
    relation: {
      type: Object,
      default: () => ({})
    },
    // 主表form数据
    mainForm: {
      type: Object,
      default: () => ({})
    },
    // page.yaml全部配置数据
    mainPage: {
      type: Object,
      default: () => ({})
    },
    mainSource: {
      type: String,
      default: ''
    },
    mainData: {
      type: Array,
      default: () => []
    },
    mainSelection: {
      type: Array,
      default: () => []
    },
    defaultQuery: {
      type: Object,
      default: () => ({})
    },
    isApprove: { type: Boolean, default: false },
    readonly: { type: Boolean, default: false }
  },
  data() {
    return {
      config: {},
      dataList: [],
      total: 0,
      dialogVisible: false,
      // mainPage: {},
      columns: [],
      isLoadingCloumns: false,
      form: {},
      isLoading: false,
      rules: {},
      multipleSelection: [],
      isBatchSelection: false, // 是否多行操作
      query: {
        page: 1,
        size: 100
      },
      conditions: {},
      queryShow: true,
      loadingInstance: null,
      formOp: null,
      formFields: [],
      formPage: null,
      formDialogVisible: false,
      orderBy: '',
      genOperations: [],
      genRelations: [],
      currenForm: {},
      isFormReadOnly: false,
      refPage: 'form', // 自定义form弹框
      refOp: null, // 当前点击的按钮
      selectionDialogVisible: false, // 选择一个列表dialog
      selectionOp: null,
      selectionConditions: {},
      selectionQuery: {},
      selectionFields: [],
      selectionPagination: {
        page: 1,
        size: 10
      },
      selectionTotal: 0,
      selectionList: [],
      selectionSelected: [],
      currentSelections: null, // 当前操作的selections
      isFullScreen: false,
      isLike: false // 是否模糊搜索
    }
  },
  computed: {
    source() {
      return this.relation?.source
    },
    sourcePage() {
      return this.relation?.sourcePage
    },
    operations() {
      return this.relation?.operations || []
    },
    relations() {
      return this.genRelations || []
    },
    relationSelections() {
      return this.relation?.selections ? [this.relation?.selections].flat() : []
    },
    pageForm() {
      return {
        ...this.mainPage?.[this.refPage]
      }
    },
    pageQuery() {
      return this.relation?.queryref ? this.mainPage?.[this.relation?.queryref] : {}
    },
    slotColumns() {
      return []
    },
    tableConfig() {
      return {
        height: '100%',
        'row-config': {
          height: 54,
          keyField: 'id',
          isHover: true,
          isCurrent: false
        },
        'edit-config': {
          enabled: this.relationSelections.length > 0 && !this.isFormReadOnly,
          trigger: 'click',
          mode: 'cell',
          showStatus: true,
          autoClear: true
        }
      }
    },
    isBasicLoading() {
      return false
    },
    showOperation() {
      if (this.isFormReadOnly) {
        return false
      }
      return (
        !!(
          this.operations && this.operations.some((o) => o.byitem && hasPermissions(o?.permissions))
        ) || !!this.relation?.selections
      )
    },
    foreignForm() {
      return this.initForeignKeyValue(this.relation, this.mainForm)
    }
  },
  watch: {
    defaultQuery: {
      async handler(val) {
        if (!this.columns?.length) {
          await this.getColumns()
        }
        Object.assign(this.conditions, val)
        this.initUseData()
        // this.getList(getGridDefaultValue(this.pageQuery, this.conditions));
      },
      immediate: true
    },
    readonly: {
      async handler(val) {
        this.isFormReadOnly = val
      },
      immediate: true
    }
  },
  created() {
    if (this.source) {
      this.getColumns()
      // this.getList()
    }
    this.$watch(
      () => [this.defaultQuery, this.mainForm],
      ([_a, b]) => {
        if (b?.id) {
          this.getList()
        }
      },
      { immediate: true }
    )
  },
  methods: {
    // 通用operation操作
    async doOperation(op, row) {
      if (op.type === 'search') {
        this.getList()
      } else if (op.type === 'route') {
        this.doRoute(row, op)
      } else if (op.type === 'url') {
        this.doUrl(row, op)
      } else if (op.type === 'search_export') {
        this.downloadList('', op)
      } else if (op.type === 'add') {
        this.showAdd(op)
      } else if (op.type === 'view') {
        this.showView(row, op)
      } else if (op.type === 'audit') {
        this.doAudit(row)
      } else if (op.type === 'edit') {
        this.showEdit(row, op)
      } else if (op.type === 'editRow') {
        this.showEditRow(row, op)
      } else if (op.type === 'delete') {
        this.showDelete(row)
      } else if (op.type === 'form') {
        this.showForm(row, op)
      } else if (op.type === 'source' && op.source) {
        this.showSourceForm(row, op)
      } else if (op.type === 'selection' && op.selection) {
        this.showSourceSelection(row, op)
      } else if (op.type === 'ajax') {
        this.doAjax(row, op)
      } else if (op.type === 'download') {
        this.doDownload(row, op)
      } else if (op.type === 'preview') {
        this.doPreview(row, op)
      } else if (op.type === 'component') {
        this.doCustomComponent(row, op)
      } else {
        if (op.loading) {
          this.loadingInstance = Loading.service({ fullscreen: true })
        }
        let data
        this.doComponentConnect(op, row, data, 'before')
        if (op.key) {
          const { data: resData } = await generalOperation({
            key: op.key,
            source: this.source,
            fields: row
          }).catch(() => {
            if (this.loadingInstance) {
              this.loadingInstance.close()
            }
          })
          data = resData
          this.getList()
        }
        this.doComponentConnect(op, row, data, 'after')
        if (this.loadingInstance) {
          this.loadingInstance.close()
        }
      }
    },
    checkVisible: checkVisible,
    checkDisabled: checkDisabled,
    // 获取能显示的按钮列表
    getShowButtons(row) {
      return (
        this.operations?.filter(
          (op) =>
            op.byitem &&
            hasPermissions(op.permissions) &&
            checkVisible(op, { ...row, $mainData: this.mainForm })
        ) || []
      )
    },
    // 组件之间的交互
    /**
     * "type": "before/after", before：执行general_operation之前调用，此时无data数据，after：执行之后调用，data为general_operation返回的数据
     * "field": "row的filed", 将eval执行的结果赋值给row[field]
     * "fields": ["row的filed"], 将eval执行的结果赋值给row[fields]
     * "eval": "调用组件的方法，包含operation, row, data参数"
     */
    async doComponentConnect(operation, row, data, type) {
      if (!operation.target) {
        return
      }
      Object.keys(operation.target).forEach(async (key) => {
        const target = operation.target[key]
        const comp = this.$parent.$parent.$refs[key]?.[0]
        console.log(this.$parent, target.eval, target.type, type)
        if (comp && target && target.eval && target.type === type) {
          console.log(`comp.${target.eval}`)
          if (type === 'before') {
            const fieldVal = eval(`comp.${target.eval}`)
            if (
              target.fields &&
              target.fields.length > 0 &&
              fieldVal &&
              typeof fieldVal === 'object'
            ) {
              target.fields.forEach(async (field) => {
                row[field] = fieldVal[field] ? fieldVal[field] : row[field]
                await editTableData({ source: this.source, fields: row })
              })
            } else if (target.field && fieldVal) {
              row[target.field] = fieldVal
              await editTableData({ source: this.source, fields: row })
            }
          } else if (type === 'after') {
            eval(`comp.${target.eval}`)
          } else {
            eval(`comp.${target.eval}`)
          }
        }
      })
    },
    async initUseData() {
      const $table = this.getMetaTableRef()
      if (this.mainData?.length && this.relation.useData === true) {
        // this.dataList = JSON.parse(JSON.stringify(this.mainData));
        this.mainData.forEach(async (item) => {
          await $table.insertAt(item)
        })
      } else if (this.mainData?.length && this.relation.useData) {
        const keys = Object.keys(this.relation.useData)
        const results = []
        this.mainData.forEach(async (item) => {
          await $table?.insertAt(
            keys.reduce((t, c) => {
              try {
                t[c] = template(this.relation.useData[c])(item)
              } catch (e) {}
            }, {})
          )
        })
        // this.dataList = results;
      }
      if ($table?.getTableData()?.fullData?.length) {
        initForeignValues($table.getTableData()?.fullData, this.columns)
      }
    },
    // 查询关系表数据
    async getList(conditions) {
      // 外键条件为空时不查询
      if (
        this.relation?.foreign_key &&
        !Object.values(this.foreignForm).some((v) => !isNullOrUnDef(v))
      ) {
        return
      }
      this.isLoading = true
      const filters = Object.keys(this.relation.filter || {}).reduce((t, c) => {
        try {
          t[c] = template(this.relation.filter[c])(this.mainForm || {})
        } catch (e) {}
        return t
      }, {})
      const res = await getTableList({
        as_dict: true,
        ...this.query,
        conditions: {
          ...conditions,
          ...filters,
          ...this.getConditions(this.conditions)
          // ...this.foreignForm,
        },
        history: this.isApprove ? true : undefined,
        source: this.source,
        order: this.orderBy
      }).finally(() => {
        this.isLoading = false
      })
      console.log('this.columns:', this.columns)
      initForeignValues(res.data, this.columns)
      this.dataList = res.data
      this.multipleSelection = []
      this.total = Number(res.count) || 0
    },
    // 打开子表selections选择弹框，查询数据
    async getSelectionList(conditions = {}) {
      const filter = this.selectionOp.selection.filter
      if (filter) {
        const row = this.selectionOp?.byitem && this.form ? this.form : this.mainForm
        Object.keys(filter).forEach((key) => {
          try {
            conditions[key] = template(filter[key])(row || {})
          } catch (e) {}
        })
      }
      console.log('-----', this.selectionOp)
      const res = await getTableList({
        ...this.query,
        page: this.selectionPagination.page,
        size: this.selectionPagination.size,
        conditions: {
          ...conditions,
          ...this.getConditions(this.selectionConditions)
        },
        like: this.isLike,
        source: this.selectionOp.selection.source
      })
      console.log(this.columns)
      initForeignValues(res.data, this.selectionFields)
      this.selectionList = res.data
      this.selectionSelected = []
      this.selectionTotal = Number(res.count) || 0
    },
    // 查询初始化子表meta数据（fields和page），
    async getColumns() {
      if (this.columns?.length || this.isLoadingCloumns) {
        return
      } else if (this.relation?.source) {
        this.isLoadingCloumns = true
        const res = await getTableMeta({
          source: this.originSource || this.relation?.source
        })
        // eslint-disable-next-line vue/no-mutating-props
        // this.relation.source = res.source
        // this.source = res.source;
        // await initRemoteValues(res.fields, this.source);
        this.columns = res.fields
        // this.mainPage = res.page;
        this.genOperations = res.page?.operations || res.operations || []
        this.genRelations = res.page?.relations || res.relations || []
      }
      // console.log("getColumns:", this.columns);
      this.rules = this.columns.reduce((t, c) => {
        if (c.editable && c.require) {
          t[c.key] = [
            {
              required: true,
              message: (c.type === 'enum' ? '请选择' : '请输入') + c.name,
              trigger: 'blur'
            }
          ]
        }
        return t
      }, {})
    },
    async showAdd(op) {
      if (op?.ref && this.mainPage?.[op.ref]) {
        this.refPage = op.ref
      } else {
        this.refPage = this.mainPage?.['formAdd'] ? 'formAdd' : 'form'
      }
      this.refOp = op
      this.form = {}
      this.dialogVisible = true
    },
    async showForm(item, op) {
      console.log(item, op)
      let itemData
      if (op.bytable && !item && this.multipleSelection.length > 0) {
        this.isBatchSelection = true
      } else if (op.byitem && !item && this.multipleSelection.length < 1) {
        ElMessage({
          type: 'info',
          message: '请选择一条记录'
        })
        return
      } else {
        itemData = item || this.multipleSelection[0]
      }
      // const form = this.columns.reduce((t, c) => {
      //   if (c.editable || c.display || c.key === 'id') {
      //     t[c.key] = itemData[c.key]
      //   }
      //   return t
      // }, {})
      this.form = {}
      // 使用自定义form
      if (op?.ref && this.mainPage?.[op.ref]) {
        this.refPage = op.ref
      } else {
        this.refPage = 'form'
      }
      this.refOp = op
      this.dialogVisible = true
      if (op.byitem && item) {
        this.form = JSON.parse(JSON.stringify(itemData))
      }
    },
    async showEdit(item, op) {
      if (!item && this.multipleSelection.length < 1) {
        ElMessage({
          type: 'info',
          message: '请选择一条记录'
        })
        return
      }
      const itemData = item || this.multipleSelection[0]
      // const form = this.columns.reduce((t, c) => {
      //   if (c.editable || c.display || c.key === 'id') {
      //     t[c.key] = itemData[c.key]
      //   }
      //   return t
      // }, {})
      // form.approvalStatus = itemData.approvalStatus
      if (op?.ref && this.mainPage?.[op.ref]) {
        this.refPage = op.ref
      } else {
        this.refPage = this.mainPage?.['formEdit'] ? 'formEdit' : 'form'
      }
      this.refOp = op
      this.form = JSON.parse(JSON.stringify(itemData))
      this.dialogVisible = true
    },
    // 显示编辑行
    async showEditRow(item, op) {
      if (!item && this.multipleSelection.length != 1) {
        ElMessage({
          type: 'info',
          message: '请选择一条记录'
        })
        return
      }
      const itemData = item || this.multipleSelection[0]
      this.refOp = op
      this.form = itemData
      this.$refs.mainTableRef?.setEditRow(itemData)
    },
    // 是否编辑行状态
    isActiveStatus(row) {
      return this.$refs.mainTableRef?.isActiveStatus(row)
    },
    // 保存编辑行
    async saveEditRow(item, op) {
      this.refOp = null
      this.form = {}
      if (this.$refs.mainTableRef?.isUpdateByRow(item)) {
        if (op?.ajax) {
          await this.doAjax(item, op)
        } else {
          await this.editSave(item)
        }
        this.$refs.mainTableRef?.saveRowEdit(item)
      } else {
        return this.$refs.mainTableRef?.cancelRowEdit(item)
      }
      this.$nextTick(() => {
        this.$refs.mainTableRef?.clearSelection()
      })
    },
    // 取消编辑行
    cancelEditRow(item) {
      this.refOp = null
      this.form = {}
      return this.$refs.mainTableRef?.cancelRowEdit(item)
    },
    async showSourceForm(item, op) {
      console.log(item, op)
      let itemData
      if (op.bytable && !op.byitem) {
      } else if (op.byitem && !item && this.multipleSelection.length < 1) {
        ElMessage({
          type: 'info',
          message: '请选择一条记录'
        })
        return
      } else {
        itemData = item || this.multipleSelection[0]
      }
      this.formOp = op
      this.formDialogVisible = true

      const res = await getTableMeta({
        source: op.source,
        page: op.sourcepage || undefined
      })
      // op.source = res.source
      // initAllValues(res.fields);
      this.formFields = res.fields
      this.formPage = res.page
      if (op.byitem) {
        this.form = JSON.parse(JSON.stringify(itemData))
      }
    },
    // 打开弹框
    async openSelection(selections) {
      console.log('0-----openSelection')
      this.currentSelections = selections
      if (this.currentSelections && this.currentSelections.type === 'form') {
        this.refPage = this.currentSelections.ref
        this.form = {}
        this.dialogVisible = true
      } else {
        const res = await getTableMeta({
          source: this.currentSelections?.source
        })
        if (this.currentSelections.source) {
          // eslint-disable-next-line vue/no-mutating-props
          // this.currentSelections.source = res.source
        }
        // initAllValues(res.fields);
        this.selectionFields = res.fields
        this.selectionQuery = this.mainPage?.[this.currentSelections?.queryref]
        this.selectionOp = {
          selection: {
            ...this.currentSelections
          }
        }
        this.getSelectionList(getGridDefaultValue(this.selectionQuery))
        this.selectionDialogVisible = true
      }
    },
    async showSourceSelection(item, op) {
      console.log(item, op)
      let itemData
      if (op.bytable && !op.byitem) {
      } else if (op.byitem && !item && this.multipleSelection.length < 1) {
        ElMessage({
          type: 'info',
          message: '请选择一条记录'
        })
        return
      } else {
        itemData = item || this.multipleSelection[0]
      }
      this.selectionDialogVisible = true
      this.selectionOp = op
      if (op.byitem) {
        this.form = JSON.parse(JSON.stringify(itemData))
      }
      const res = await getTableMeta({
        source: op.selection.source
      })
      // op.selection.source = res.source
      // initAllValues(res.fields);
      this.selectionFields = res.fields
      this.selectionQuery = this.mainPage?.[op.selection?.queryref]
      this.getSelectionList(getGridDefaultValue(this.selectionQuery))
    },
    // 设置外键值
    initForeignKeyValue(relation, form) {
      const result = {}
      if (!relation.foreign_key) {
        return
      }
      if (typeof relation.foreign_key === 'string') {
        result[relation.foreign_key] = form?.id
      } else {
        Object.keys(relation.foreign_key).forEach((key) => {
          try {
            result[key] = template(relation.foreign_key[key])(form || {})
          } catch (e) {}
        })
      }
      return result
    },
    // selections弹框确认，将数据添加到子表
    async addSelection() {
      if (this.relation?.selections && this.currentSelections) {
        const $table = this.getMetaTableRef()
        for (let i = 0; i < this.selectionSelected.length; i++) {
          const sel = this.selectionSelected[i]
          // 如果选择的表和主表是同一个表，不能添加自己
          if (this.currentSelections?.source === this.mainSource) {
            if (sel.id === this.mainForm.id) {
              ElMessage.warning('不能添加自己')
              return
            }
          }
          const form = {}
          this.selectionFields.forEach((fd) => {
            if (fd.value !== null && fd.value !== undefined) {
              form[fd.key] = fd.value
            } else {
              form[fd.key] = undefined
            }
          })
          Object.keys(this.currentSelections.form).forEach((key) => {
            try {
              form[key] = template(this.currentSelections.form[key])(sel || {})
            } catch (e) {}
          })
          initSelectValues(form, this.selectionFields, sel)
          this.columns.forEach((col) => {
            if (col.key?.includes('.')) {
              form[col.key] = form[col.key] || ''
            }
          })
          // 设置外键id
          Object.assign(form, this.foreignForm)
          if ($table) {
            if (
              this.currentSelections?.uniqueField &&
              !isUniqueData(
                $table.getTableData()?.fullData || [],
                form,
                this.currentSelections?.uniqueField
              )
            ) {
              ElMessage.warning('选择的数据已添加')
              return
            }
            await $table.insertAt(form)
          }
        }
        this.selectionDialogVisible = false
        initForeignValues($table.getTableData()?.fullData, this.columns)
      } else {
        if (this.selectionSelected.length != 1) {
          ElMessage({
            type: 'info',
            message: '请选择一条记录'
          })
          return
        }
        const $table = this.$refs.selectionTableRef?.tableRef
        const sel = this.selectionSelected[0]
        Object.keys(this.selectionOp.selection.form).forEach((key) => {
          try {
            this.form[key] = template(this.selectionOp.selection.form[key])(sel || {})
          } catch (e) {}
        })
        if (this.selectionOp?.ajax) {
          await this.doAjax(this.form, this.selectionOp)
          this.getList()
        } else {
          this.$refs.mainTableRef?.reloadRow(row)
        }
        this.selectionDialogVisible = false
      }
    },
    async showView(item, op) {
      if (!item && this.multipleSelection.length < 1) {
        ElMessage({
          type: 'info',
          message: '请选择一条记录'
        })
        return
      }
      const itemData = item || this.multipleSelection[0]
      // const form = this.columns.reduce((t, c) => {
      //   if (c.editable || c.display || c.key === 'id') {
      //     t[c.key] = itemData[c.key]
      //   }
      //   return t
      // }, {})
      // form.approvalStatus = itemData.approvalStatus
      if (op?.ref && this.mainPage?.[op.ref]) {
        this.refPage = op.ref
      } else {
        this.refPage = this.mainPage?.['formView'] ? 'formView' : 'form'
      }
      this.isFormReadOnly = true
      this.form = JSON.parse(JSON.stringify(itemData))
      this.dialogVisible = true
    },
    async showDelete(item) {
      console.log(this.operations)
      if (!item && this.multipleSelection.length < 1) {
        ElMessage({
          type: 'info',
          message: '请选择要删除的记录'
        })
        return
      }
      if (!this.mainForm?.id) {
        const $table = this.getMetaTableRef()
        $table.removeCheckboxRow()
        return
      }
      ElMessageBox.confirm(`确认删除选择的记录?`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
        confirmButtonClass: 'el-button--danger'
      })
        .then(async () => {
          const allItems = item ? [item] : this.multipleSelection
          // console.log(allItems)
          // await Promise.all(
          //   allItems.map((t) =>
          //     deleteTableData({
          //       id: [t.id],
          //       source: this.source
          //     })
          //   )
          // )
          await deleteTableData({
            id: allItems.map((t) => t.id),
            source: this.source
          })
          this.getList()
          ElMessage({
            type: 'success',
            message: '删除成功!'
          })
        })
        .catch(() => {})
    },
    doDeleteTableData(row) {
      ElMessageBox.confirm(`确认删除?`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
        confirmButtonClass: 'el-button--danger'
      })
        .then(async () => {
          if (this.currentSelections?.type === 'form') {
            await deleteTableData({
              source: this.relation.source,
              id: [row.id]
            })
            this.getList()
          } else {
            const $table = this.getMetaTableRef()
            if ($table) {
              $table.remove(row)
            }
          }
        })
        .catch(() => {})
    },
    // 点击按钮执行一个ajax
    // ajax: {
    //   url: "/basic/getConfigs",
    //   params: {
    //     partnumber: "${取行字段数据}"
    //   },
    //   results: {
    //     partnumber: "${可以取返回结果字段，赋值给行字段}"
    //   },
    //   confirm: "请使用${可以取返回结果字段}",
    //   message: "成功${可以取返回结果字段}"
    // }
    async doAjax(row, op, isBatch = false) {
      // const op = {
      //   ajax: {
      //     url: "/basic/getConfigs",
      //     params: {
      //       partnumber: "${partnumber}"
      //     },
      //     results: {
      //       partnumber: "${title}"
      //     },
      //     confirm: "请使用${title}",
      //     message: "成功${title}"
      //   }
      // }
      const url = op.ajax.url
      if (url) {
        if (op.ajax.exec?.func && func[op.ajax.exec?.func]) {
          if (op.ajax.batch) {
            const paramList = this.multipleSelection.map((item) => {
              const res = op.ajax.params
                ? Object.keys(op.ajax.params || {}).reduce(
                    (t, c) => {
                      try {
                        const compiled = template(op.ajax.params[c])
                        t[c] = compiled({ ...item, ...row })
                        return t
                      } catch (e) {
                        return t
                      }
                    },
                    this.refOp?.ajax ? { ...item, ...row } : {}
                  )
                : { ...item, ...row }
              // 设置外键id
              Object.assign(res, this.foreignForm)
              return res
            })
            // 定制化
            if (!func[op.ajax.exec?.func](paramList)) {
              return
            }
          } else {
            if (!func[op.ajax.exec?.func](row)) {
              return
            }
          }
        }

        if (!row && !this.multipleSelection?.length) {
          ElMessage({
            type: 'info',
            message: '请至少选择一条记录'
          })
          return
        }
        let confirm = op.ajax.confirm || ''
        // 配置有config弹出确认框
        if (confirm) {
          try {
            const compiled = template(confirm)
            confirm = compiled(row || {})
          } catch (e) {}
          const isConfirmed = await new Promise((resolve, reject) => {
            ElMessageBox.confirm(`${confirm}`, '提示', {
              confirmButtonText: '确定',
              cancelButtonText: '取消',
              type: 'warning'
            })
              .then(() => {
                resolve(true)
              })
              .catch(() => {
                reject(false)
              })
          })
          if (!isConfirmed) {
            return
          }
        }
        const method = op.ajax.method || 'get'
        const results = op.ajax.results // 执行成功后，修改row数据
        const message = op.ajax.message || '' // 执行成功后，提示信息
        const isAutoBatch = !row || (op.bytable && !op.byitem)
        // 单条记录
        if (row && (!isBatch || isAutoBatch)) {
          const params = op.ajax.params
            ? Object.keys(op.ajax.params || {}).reduce(
                (t, c) => {
                  try {
                    const compiled = template(op.ajax.params[c])
                    t[c] = compiled(row)
                    return t
                  } catch (e) {
                    return t
                  }
                },
                this.refOp?.ajax ? row : {}
              )
            : row
          if (isAutoBatch) {
            params.ids = this.multipleSelection.map((x) => x.id)
          }
          // 设置外键id
          Object.assign(params, this.foreignForm)
          this.isLoading = true
          await doApi(url, params, method)
            .then((data) => {
              // form执行的ajax
              if (this.refOp?.ajax) {
                this.dialogVisible = false
              }
              // 如果配置了result就不查询
              if (row && data && results) {
                Object.keys(results).forEach((field) => {
                  const compiled = template(results[field])
                  row[field] = compiled(data)
                  this.$refs.mainTableRef?.reloadRow(row, field)
                })
              } else {
                this.getList()
              }
              // 提示i信息
              if (row && message) {
                try {
                  const compiled = template(message)
                  ElMessage.success(compiled(data))
                } catch (e) {
                  ElMessage.success(message)
                }
              }
            })
            .finally(() => {
              this.isLoading = false
            })
        } else if (this.multipleSelection?.length > 0) {
          if (op.ajax.batch) {
            const paramList = this.multipleSelection.map((item) => {
              const res = op.ajax.params
                ? Object.keys(op.ajax.params || {}).reduce(
                    (t, c) => {
                      try {
                        const compiled = template(op.ajax.params[c])
                        t[c] = compiled({ ...item, ...row })
                        return t
                      } catch (e) {
                        return t
                      }
                    },
                    this.refOp?.ajax ? { ...item, ...row } : {}
                  )
                : { ...item, ...row }
              // 设置外键id
              Object.assign(res, this.foreignForm)
            })
            // 定制化
            if (op.ajax.exec?.func && func[op.ajax.exec?.func]) {
              if (!func[op.ajax.exec?.func](paramList)) {
                return
              }
            }
            doApi(url, paramList, method)
              .then((res) => {
                const firstRow = this.multipleSelection[0]
                const firstData = datas[0]
                // 提示i信息
                if (firstRow && message) {
                  try {
                    const compiled = template(message)
                    ElMessage.success(compiled(firstData))
                  } catch (e) {
                    ElMessage.success(message)
                  }
                }
                this.getList()
              })
              .finally(() => {
                this.isLoading = false
                this.dialogVisible = false
              })
          } else {
            const allPromise = this.multipleSelection.map((item) => {
              const params = op.ajax.params
                ? Object.keys(op.ajax.params || {}).reduce(
                    (t, c) => {
                      try {
                        const compiled = template(op.ajax.params[c])
                        t[c] = compiled({ ...item, ...row })
                        return t
                      } catch (e) {
                        return t
                      }
                    },
                    this.refOp?.ajax ? { ...item, ...row } : {}
                  )
                : { ...item, ...row }
              // 设置外键id
              Object.assign(params, this.foreignForm)
              this.isLoading = true
              return doApi(url, params, method)
            })
            Promise.all(allPromise)
              .then((datas) => {
                // form执行的ajax
                if (this.refOp?.ajax) {
                  this.dialogVisible = false
                }
                const firstRow = this.multipleSelection[0]
                const firstData = datas[0]
                // 提示i信息
                if (firstRow && message) {
                  try {
                    const compiled = template(message)
                    ElMessage.success(compiled(firstData))
                  } catch (e) {
                    ElMessage.success(message)
                  }
                }
                this.getList()
              })
              .finally(() => {
                this.isLoading = false
                this.dialogVisible = false
              })
          }
        }
      }
    },
    // 弹框一个自定义组件页面（需放在./views/目录下）
    async doCustomComponent(row, op) {
      if (op?.component?.module) {
        let compTitle = op?.component?.title || ''
        if (compTitle) {
          try {
            compTitle = template(compTitle)(row || {})
          } catch (e) {}
        }
        const MyAsyncComponent = defineAsyncComponent(
          modules[`../views/${op.component.module}.vue`]
        )
        ElMessageBox({
          title: compTitle,
          ...op?.component?.props,
          message: () =>
            h(MyAsyncComponent, {
              data: row || this.mainForm,
              op,
              mainSelection: this.mainSelection,
              meta: this.columns,
              onClose: (bool) => {
                ElMessageBox.close()
                if (bool) {
                  this.getList()
                }
              }
            }),
          customStyle: op?.component?.style,
          customClass: 'custom-component',
          showConfirmButton: false,
          showCancelButton: false,
          callback: () => {
            this.getList()
          }
        })
      }
    },
    // 点击按钮执行一个文件预览
    async doPreview(row, op) {
      let previewContent = ''
      // 配置了ajax
      if (op.ajax) {
        const url = op.ajax.url
        const method = op.ajax.method || 'get'
        if (!row && this.multipleSelection?.length) {
          row = this.multipleSelection[0]
        }
        const params = op.ajax.params
          ? Object.keys(op.ajax.params || {}).reduce((t, c) => {
              try {
                const compiled = template(op.ajax.params[c])
                t[c] = compiled(row)
                return t
              } catch (e) {
                return t
              }
            }, {})
          : row
        if (op.bytable && !row) {
          params.ids = this.multipleSelection.map((item) => item.id)
        }
        // 配置了pattern去返回内容
        if (op.ajax.pattern) {
          this.isLoading = true
          await doApi(url, params, method)
            .then((res) => {
              console.log(res)
              previewContent = getTemplateData(op.ajax.pattern, res)
            })
            .finally(() => {
              this.isLoading = false
            })
        } else {
          // 未配置pattern认为ajax返回二进制文件
          this.isLoading = true
          await doAjaxDownload(url, params, method)
            .then((res) => {
              const blob = new Blob([res.data])
              const downloadUrl = window.URL.createObjectURL(blob)
              previewContent = downloadUrl
            })
            .finally(() => {
              this.isLoading = false
            })
        }
      } else {
        previewContent = getTemplateData(op.pattern, row)
      }
      doPreview(previewContent, op.preview)
    },
    // 点击按钮执行一个ajax导出文件
    // ajax: {
    //   url: "/basic/getConfigs",
    //   params: {
    //     partnumber: "${取行字段数据}"
    //   },
    //   confirm: "请使用${可以取返回结果字段}",
    //   filename: "文件名${可以取返回结果字段}.xlsx"
    // }
    async doDownload(row, op) {
      console.log(row, op)
      const url = op.ajax.url
      if (url) {
        if (op.bytable && !row) {
          // const allIds = this.multipleSelection.map((item) => item.id);
          row = this.mainForm
        }
        let confirm = op.ajax.confirm || ''
        // 配置有config弹出确认框
        if (confirm) {
          try {
            const compiled = template(confirm)
            confirm = compiled(row || {})
          } catch (e) {}
          const isConfirmed = await new Promise((resolve, reject) => {
            ElMessageBox.confirm(`${confirm}`, '提示', {
              confirmButtonText: '确定',
              cancelButtonText: '取消',
              type: 'warning'
            })
              .then(() => {
                resolve(true)
              })
              .catch(() => {
                reject(false)
              })
          })
          if (!isConfirmed) {
            return
          }
        }
        const method = op.ajax.method || 'get'
        const params = op.ajax.params
          ? Object.keys(op.ajax.params || {}).reduce(
              (t, c) => {
                try {
                  const compiled = template(op.ajax.params[c])
                  t[c] = compiled(row)
                  return t
                } catch (e) {
                  return t
                }
              },
              this.refPage !== 'form' && this.refOp ? row : {}
            )
          : row
        // 设置外键id
        Object.assign(params, this.foreignForm)
        this.isLoading = true
        let fileName = `${Date.now()}.xlsx`
        if (op.ajax.filename) {
          try {
            fileName = template(op.ajax.filename)(row)
          } catch (e) {}
        }
        await doAjaxDownload(url, params, method)
          .then((res) => {
            if (!op.ajax.filename) {
              const contentDisposition = res.headers['content-disposition']
              if (contentDisposition && contentDisposition.includes('filename')) {
                const filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/
                const matches = filenameRegex.exec(contentDisposition)
                if (matches != null && matches[1]) {
                  const metchName = matches[1].replace(/['"]/g, '') // 去除引号
                  fileName = decodeURIComponent(metchName.replace('utf-8', ''))
                }
              }
            }
            const blob = new Blob([res.data])
            const downloadUrl = window.URL.createObjectURL(blob)
            const a = document.createElement('a')
            a.style.display = 'none'
            a.href = downloadUrl
            a.download = fileName // 设置下载文件的默认名
            document.body.appendChild(a)
            a.click()
            window.URL.revokeObjectURL(downloadUrl) // 释放 URL 对象
            document.body.removeChild(a)
          })
          .finally(() => {
            this.isLoading = false
            this.dialogVisible = false
          })
      }
    },
    doUrl(row, op) {
      if (op.pattern) {
        const url = getTemplateData(op.pattern, row)
        const a = document.createElement('a')
        a.target = '_blank'
        a.href = url
        a.click()
      } else {
        const route = this.$router.resolve(getTemplateData(op.route, row))
        const a = document.createElement('a')
        a.target = '_blank'
        a.href = route.href
        a.click()
      }
    },
    // 跳转路由
    async doRoute(row, op) {
      if (op.pattern) {
        this.$router.push(getTemplateData(op.pattern, row))
      } else {
        const path = op.route.path
        if (path) {
          let confirm = op.route.confirm || ''
          // 配置有config弹出确认框
          if (confirm) {
            try {
              const compiled = template(confirm)
              confirm = compiled(row || {})
            } catch (e) {}
            const isConfirmed = await new Promise((resolve, reject) => {
              ElMessageBox.confirm(`${confirm}`, '提示', {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning'
              })
                .then(() => {
                  resolve(true)
                })
                .catch(() => {
                  reject(false)
                })
            })
            if (!isConfirmed) {
              return
            }
          }
          const params = op.route.params
            ? Object.keys(op.route.params || {}).reduce((t, c) => {
                try {
                  t[c] = template(op.route.params[c])(row)
                  return t
                } catch (e) {
                  return t
                }
              }, {})
            : {}
          // 跳转路由传参使用sessionStorage，路由带query菜单显示会有问题
          sessionStorage.setItem('pageroute', JSON.stringify({ path, params }))
          this.$router.push({
            path
          })
        }
      }
    },
    async doSaveForm() {
      const valid = await this.$refs.revFormRef?.validate()
      if (!valid) {
        return
      }
      const relationTable = this.$refs.relationRef
      if (relationTable && !(await relationTable.editValidate())) {
        return
      }
      this.isLoading = true
      if (this.formOp.loading) {
        this.loadingInstance = Loading.service({ fullscreen: true })
      }
      const { data } = await generalOperation({
        key: this.formOp.key,
        source: this.source,
        form: this.formFields
      }).catch(() => {
        this.isLoading = false
      })
      if (data) {
        this.dataList = data
        this.multipleSelection = []
      } else {
        this.getList()
      }
      if (this.loadingInstance) {
        this.loadingInstance.close()
      }
      ElMessage({ type: 'success', message: '保存成功' })
      this.formDialogVisible = false
      this.isLoading = false
    },
    onCellOperation(col, row) {
      const operation = col.operation
      if (typeof operation === 'string') {
        const findOp = this.operations.find((op) => op.key === operation)
        this.doOperation(findOp, row)
      } else if (operation) {
        this.doOperation(operation, row)
      }
    },
    sortChange({ field, order }) {
      if (order) {
        this.orderBy = `${field} ${order}`
      } else {
        this.orderBy = ''
      }
      this.getList()
    },
    currentChange({ rowIndex, row }) {
      // console.log(rowIndex, row)
      // this.currenForm = row
    },
    async editSave(form) {
      this.isLoading = true
      await editTableData({
        source: this.source,
        fields: { ...form, ...this.foreignForm }
      })
      ElMessage({ type: 'success', message: '保存成功' })
      this.isLoading = false
    },
    async doSave() {
      const validateForm = this.$refs.form || this.$refs.tableForm
      validateForm.validate(async (valid) => {
        if (valid) {
          const relationTable = this.$refs.relationRef
          if (relationTable && !(await relationTable.editValidate())) {
            return
          }
          // 如果主表没有保存
          if (!this.mainForm?.id) {
            const $table = this.getMetaTableRef()
            $table.insertAt({ ...this.form, ...this.foreignForm })
            this.dialogVisible = false
            this.formDialogVisible = false
            this.isLoading = false
            return
          }
          if (this.refOp && this.refOp.ajax) {
            this.doAjax({ ...this.form, ...this.foreignForm }, this.refOp, this.isBatchSelection)
          } else {
            this.isLoading = true
            if (this.form.id) {
              const res = await editTableData({
                source:
                  this.formOp?.source && this.formDialogVisible ? this.formOp.source : this.source,
                fields: { ...this.form, ...this.foreignForm }
              }).catch(() => {
                this.isLoading = false
              })
              if (res === null || res === undefined) {
                return
              }
              console.log(res)
            } else {
              const res = await addTableData({
                source:
                  this.formOp?.source && this.formDialogVisible ? this.formOp.source : this.source,
                fields: { ...this.form, ...this.foreignForm }
              }).catch(() => {
                this.isLoading = false
              })
              this.form.id = res
            }
            const relationList = this.$refs.relationRef?.getRelationDatas()
            const allPromise = relationList?.map((relation) => [
              relation.insertList?.map((form) => {
                const foreingParams = {}
                const foreignKey = relation.foreign_key
                if (typeof foreignKey === 'string') {
                  foreingParams[relation.foreign_key] = this.form.id
                } else if (foreignKey && typeof foreignKey === 'object') {
                  Object.keys(foreignKey).forEach((key) => {
                    try {
                      foreingParams[key] = template(foreignKey[key])(this.form)
                    } catch (e) {}
                  })
                }
                return addTableData({
                  source: relation.source,
                  fields: {
                    ...form,
                    id: undefined,
                    ...foreingParams,
                    ...this.foreignForm
                  }
                })
              }),
              relation.updateList?.map((form) =>
                editTableData({
                  source: relation.source,
                  fields: { ...form, ...this.foreignForm }
                })
              ),
              relation.removeList?.map((form) =>
                deleteTableData({ source: relation.source, id: [form.id] })
              )
            ])
            if (allPromise?.length > 0) {
              await Promise.all(allPromise?.flat())
              this.$refs.relationRef?.initColumns()
            }
            this.getList()
            ElMessage({ type: 'success', message: '保存成功' })
            this.dialogVisible = false
            this.formDialogVisible = false
            this.isLoading = false
          }
        }
      })
    },
    // 提交审批
    async doAudit(item) {
      const itemData = item || this.form
      // 如果是弹框
      if (this.dialogVisible) {
        const validateForm = this.$refs.form || this.$refs.tableForm
        const validated = await new Promise((resolve, reject) => {
          validateForm.validate((valid) => {
            if (valid) {
              resolve(true)
            } else {
              reject(false)
            }
          })
        })
        if (!validated) {
          return
        }
      }
      ElMessageBox.confirm(`确认提交审批?`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      })
        .then(async () => {
          this.isLoading = true
          if (itemData.id) {
            const submitList = [
              {
                source: this.source,
                fields: itemData,
                op: itemData.approvalStatus === 3 ? 1 : 0
              }
            ]
            const relationList = this.$refs.relationRef?.getRelationDatas()
            relationList?.forEach((relation) => {
              if (itemData.approvalStatus === 0) {
                submitList.push(
                  ...(relation.allList?.map((form) => ({
                    source: relation.source,
                    op: 0,
                    fields: { ...form, id: /^\d+$/.test(form.id) ? form.id : undefined }
                  })) || [])
                )
              } else {
                submitList.push(
                  ...(relation.insertList?.map((form) => ({
                    source: relation.source,
                    op: 0,
                    fields: { ...form, id: undefined }
                  })) || [])
                )
                submitList.push(
                  ...(relation.updateList?.map((form) => ({
                    source: relation.source,
                    op: 1,
                    fields: form
                  })) || [])
                )
                submitList.push(
                  ...(relation.removeList?.map((form) => ({
                    source: relation.source,
                    op: 2,
                    id: form.id
                  })) || [])
                )
              }
            })
            console.log(submitList)
            const res = await auditAllTableData({ data: submitList }).finally(() => {
              this.isLoading = false
            })
            if (res === null || res === undefined) {
              return
            }
            console.log(res)
          }
          // if (itemData.id) {
          //   const res = await auditTableData({
          //     source: this.source,
          //     fields: itemData
          //   }).catch(() => {
          //     this.isLoading = false
          //   })
          //   if (res===null || res===undefined) {
          //     return;
          //   }
          //   console.log(res)
          // }
          this.getList()
          this.dialogVisible = false
          ElMessage({
            type: 'success',
            message: '提交审批成功!'
          })
        })
        .catch(() => {})
    },
    // 导出excel
    downloadList(command, op) {
      // 根据查询条件导出所有数据
      if (command === 'all') {
        this.isLoading = true
        op._loading = true
        exportTableData({
          conditions: this.getConditions(this.conditions),
          source: this.source
        })
          .then((res) => {
            window.location.href = res.download_url
          })
          .finally(() => {
            setTimeout(() => {
              this.isLoading = false
              op._loading = false
            }, 500)
          })
      } else if (command === 'select') {
        // 导出选中的数据
        downloadLists(this.columns, this.multipleSelection)
      } else {
        // 导出当前页
        downloadLists(this.columns, this.dataList)
      }
    },
    onUploadSuccess() {
      this.getList()
    },
    getConditions(conds) {
      const result = {}
      Object.keys(conds).forEach((key) => {
        if (
          (conds[key] && Array.isArray(conds[key]) && conds[key].join('').length < 1) ||
          !conds[key]
        ) {
          // console.log("xxxxx");
        } else {
          result[key] = conds[key]
        }
      })
      return result
    },
    resetQuery() {
      this.$refs.queryMeta.resetForm()
      // this.conditions = {};
    },
    resetSelectQuery() {
      this.$refs.selectionQueryMeta.resetForm()
      // this.conditions = {};
    },
    formDialogClose() {
      const validForm = this.$refs.form || this.$refs.tableForm
      if (validForm) {
        validForm.resetFields()
        this.form = {}
      }
      const relationRef = this.$refs.relationRef
      if (relationRef) {
        relationRef.revertData()
      }
      this.relations?.forEach((relation) => {
        relation.list = []
      })
      this.formOp = null
      this.formFields = []
      this.formPage = null
      this.formDialogVisible = false
    },
    dialogClose() {
      const validForm = this.$refs.form || this.$refs.tableForm
      if (validForm) {
        validForm.resetFields()
        this.form = {}
      }
      const relationRef = this.$refs.relationRef
      if (relationRef) {
        relationRef.revertData()
      }
      this.relations?.forEach((relation) => {
        relation.list = []
      })
      this.isBatchSelection = false
      this.isFormReadOnly = false
      this.refPage = 'form'
      this.refOp = null
      this.selectionOp = null
      this.selectionConditions = {}
      this.selectionQuery = {}
      this.selectionFields = []
      this.selectionList = []
      this.selectionSelected = []
      this.currentSelections = null
    },
    handleSelectionChange(val) {
      this.multipleSelection = val
    },
    handleSizeChange(val) {
      this.query.page = 1
      this.query.size = val
      this.getList()
    },
    handleCurrentChange(val) {
      this.query.page = val
      this.getList()
    },
    handleSizeChangeSelection(val) {
      this.selectionPagination.page = 1
      this.selectionPagination.size = val
      this.getSelectionList()
    },
    handleCurrentChangeSelection(val) {
      this.selectionPagination.page = val
      this.getSelectionList()
    },
    getSource() {
      return this.source
    },
    getMetaTableRef() {
      return this.$refs.mainTableRef?.tableRef
    },
    async editValidate(row) {
      // 配置了require，子表提交不能为空
      if (!row && this.relation?.require) {
        const needCheck = [this.relation?.require]
          .flat()
          .some((vis) =>
            Object.keys(vis).every((key) => [vis[key]].flat().includes(this.mainForm[key]))
          )
        const tableData = this.getMetaTableRef()?.getTableData()?.tableData
        if (needCheck && !tableData?.length) {
          ElMessage({ type: 'warning', message: '请添加' + this.relation?.title })
          return Promise.reject(false)
        }
      }
      return this.$refs.mainTableRef?.editValidate(row)
    },
    getPermissions(permissions) {
      return getPermissions(permissions)
    },
    hasPermissions(permissions) {
      return hasPermissions(permissions)
    }
  }
}
</script>

<style lang="less" scoped>
.rev-table {
  width: 100%;
  height: 100%;
  padding: 15px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  flex: 1;

  &.relation-table {
    padding: 0;

    .main-table {
      min-height: 352px;
    }
  }

  .table-title {
    padding-bottom: 10px;
    font-weight: bold;
  }

  .query-tools {
    margin-bottom: 10px;
    display: flex;
    justify-content: space-between;

    :deep(.el-button) {
      i.el-icon {
        margin-right: 0 !important;
      }
    }

    .op-btn {
      padding: 8px 15px;

      img {
        height: 13px;
        line-height: 0;
        margin-right: 5px;
        vertical-align: middle;
      }

      .text {
        vertical-align: middle;
      }
    }

    .query-upload {
      display: inline-block;
      vertical-align: middle;
      margin-right: 10px;
      margin-left: 10px;
    }
  }

  .text-btn {
    padding: 3px 5px;
    margin-left: 0;

    img {
      height: 14px;
      vertical-align: middle;
      margin-right: 3px;
    }

    .text {
      vertical-align: middle;
    }
  }

  .main-table {
    min-height: 531px;
    overflow: hidden;
    position: relative;
    flex: 1;
  }

  .table-pagination {
    margin-top: 10px;
    text-align: right;
  }

  .layout-full {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    padding: 15px;
    overflow: hidden;
    display: flex;
    flex-direction: column;

    .main-table {
      min-height: 200px;
    }
  }
}
</style>
